
#include <GL/gl.h>
#include <math.h>
#include <stdio.h>

#include "o_objet.h"
#include "u_table.h"
#include "t_geometrie.h"

struct reparametrage
{
  Table_quadruplet Pts_Controle_recalcule;
  Table_quadruplet Pts_Controle;
  Table_quadruplet Courbe_reparametree;
  int nb_points;
  int debut;
  int fin;
};

/*/// ################################################################################################################################ \\\*/

Table_quadruplet calcul_pt_control_debut(struct reparametrage *o)
{
    int i,j;
    double debut = 1.0*o->debut/100;

    for(i=0;i<o->Pts_Controle.nb;i++)
    {
        o->Pts_Controle_recalcule.table[i] = o->Pts_Controle.table[i];
        o->Pts_Controle_recalcule.table[i].x *= o->Pts_Controle_recalcule.table[i].h;
        o->Pts_Controle_recalcule.table[i].y *= o->Pts_Controle_recalcule.table[i].h;
        o->Pts_Controle_recalcule.table[i].z *= o->Pts_Controle_recalcule.table[i].h;
    }

    for(i=1;i<o->Pts_Controle.nb;i++)
    {
        for(j=0;j<o->Pts_Controle.nb-i;j++)
        {
            o->Pts_Controle_recalcule.table[j].x = (1 - debut) * o->Pts_Controle_recalcule.table[j].x + debut * o->Pts_Controle_recalcule.table[j+1].x;
            o->Pts_Controle_recalcule.table[j].y = (1 - debut) * o->Pts_Controle_recalcule.table[j].y + debut * o->Pts_Controle_recalcule.table[j+1].y;
            o->Pts_Controle_recalcule.table[j].z = (1 - debut) * o->Pts_Controle_recalcule.table[j].z + debut * o->Pts_Controle_recalcule.table[j+1].z;
            o->Pts_Controle_recalcule.table[j].h = (1 - debut) * o->Pts_Controle_recalcule.table[j].h + debut * o->Pts_Controle_recalcule.table[j+1].h;
        }
    }
    return o->Pts_Controle_recalcule;
}

Table_quadruplet calcul_pt_control_fin(struct reparametrage *o)
{
    int i,j;
    Table_quadruplet points_temp;
    ALLOUER(points_temp.table,o->Pts_Controle_recalcule.nb);
    double fin = 1.0*o->fin/100;

    for(i=0;i<o->Pts_Controle_recalcule.nb;i++)
    {
        points_temp.table[i]=o->Pts_Controle_recalcule.table[i];
    }


    for(i=1;i<o->Pts_Controle.nb;i++)
    {
        for(j=0;j<o->Pts_Controle.nb-i;j++)
        {
            if(j==0)
            {
                o->Pts_Controle_recalcule.table[i].x = (1 - fin) * points_temp.table[j].x + fin * points_temp.table[j+1].x;
                o->Pts_Controle_recalcule.table[i].y = (1 - fin) * points_temp.table[j].y + fin * points_temp.table[j+1].y;
                o->Pts_Controle_recalcule.table[i].z = (1 - fin) * points_temp.table[j].z + fin * points_temp.table[j+1].z;
                o->Pts_Controle_recalcule.table[i].h = (1 - fin) * points_temp.table[j].h + fin * points_temp.table[j+1].h;
            }

            points_temp.table[j].x = (1 - fin) * points_temp.table[j].x + fin * points_temp.table[j+1].x;
            points_temp.table[j].y = (1 - fin) * points_temp.table[j].y + fin * points_temp.table[j+1].y;
            points_temp.table[j].z = (1 - fin) * points_temp.table[j].z + fin * points_temp.table[j+1].z;
            points_temp.table[j].h = (1 - fin) * points_temp.table[j].h + fin * points_temp.table[j+1].h;
        }
    }

    for(i=0;i<o->Pts_Controle.nb;i++)
    {
        o->Pts_Controle_recalcule.table[i].x /= o->Pts_Controle_recalcule.table[i].h;
        o->Pts_Controle_recalcule.table[i].y /= o->Pts_Controle_recalcule.table[i].h;
        o->Pts_Controle_recalcule.table[i].z /= o->Pts_Controle_recalcule.table[i].h;
    }
    free(points_temp.table);
    return o->Pts_Controle_recalcule;
}

/*/// ################################################################################################################################ \\\*/

Quadruplet calcul_point_courbe(struct reparametrage *o,double pas) /// crée la courbe reparametrée
{
    int i,j;
    Table_quadruplet points_temp;
    ALLOUER(points_temp.table,o->Courbe_reparametree.nb);
    Quadruplet resultat;

    for(j=0;j < o->Pts_Controle_recalcule.nb;j++)
    {
        points_temp.table[j] = o->Pts_Controle_recalcule.table[j];
        points_temp.table[j].x*=points_temp.table[j].h;
        points_temp.table[j].y*=points_temp.table[j].h;
        points_temp.table[j].z*=points_temp.table[j].h;
    }


    for(i=1;i < o->Pts_Controle_recalcule.nb;i++)
    {
        for(j=0;j<o->Pts_Controle_recalcule.nb-i;j++)
        {
            points_temp.table[j].x = (1 - pas) * points_temp.table[j].x + pas * points_temp.table[j+1].x;
            points_temp.table[j].y = (1 - pas) * points_temp.table[j].y + pas * points_temp.table[j+1].y;
            points_temp.table[j].z = (1 - pas) * points_temp.table[j].z + pas * points_temp.table[j+1].z;
            points_temp.table[j].h = (1 - pas) * points_temp.table[j].h + pas * points_temp.table[j+1].h;
        }
    }
    j--;
    points_temp.table[j].x/=points_temp.table[j].h;
    points_temp.table[j].y/=points_temp.table[j].h;
    points_temp.table[j].z/=points_temp.table[j].h;
    resultat= points_temp.table[j];
    free(points_temp.table);
    return resultat;
}

Table_quadruplet calcul_reparametrage(struct reparametrage *o)
{
    double i;
    double pas =0.0;
    int indice = 0;
    pas = 1.0/o->nb_points;

    for(i = 0; i <= 1 ;i+=pas,indice++)
        o->Courbe_reparametree.table[indice] = calcul_point_courbe(o,i);

    return o->Courbe_reparametree;
}


static void changement_reparametrage(struct reparametrage *o)
{
    if ( ! (UN_CHAMP_CHANGE(o)||CREATION(o)) )
        return;

    if (CHAMP_CHANGE(o, nb_points) ||  CHAMP_CHANGE(o, Pts_Controle) || CHAMP_CHANGE(o, debut) || CHAMP_CHANGE(o, fin) )
    {
        if (o->nb_points > 0 || o->Courbe_reparametree.nb >=2 || o->Pts_Controle_recalcule.nb >=0 ||o->debut != 0 || o->fin != 100)
        {
            free(o->Courbe_reparametree.table);
            free(o->Pts_Controle_recalcule.table);
        }

        if(o->nb_points < 20)
            o->nb_points=20;

        ALLOUER(o->Pts_Controle_recalcule.table,o->Pts_Controle.nb);
        o->Pts_Controle_recalcule.nb = o->Pts_Controle.nb;

      ALLOUER(o->Courbe_reparametree.table,o->nb_points);
      o->Courbe_reparametree.nb = o->nb_points;

        o->Pts_Controle_recalcule=calcul_pt_control_debut(o);
        o->Pts_Controle_recalcule=calcul_pt_control_fin(o);

        o->Courbe_reparametree=calcul_reparametrage(o);

      printf("dans changement Bezier\n");
    }
}


static void affiche_courbe_reparametree(struct reparametrage *o)
{
    int j;

    glBegin(GL_LINE) ;
    glColor3d(1,0,0);
    for(j=0; j < o->Pts_Controle_recalcule.nb-1; j++){
        glVertex3f(o->Pts_Controle_recalcule.table[j].x,o->Pts_Controle_recalcule.table[j].y,o->Pts_Controle_recalcule.table[j].z);
        glVertex3f(o->Pts_Controle_recalcule.table[j+1].x,o->Pts_Controle_recalcule.table[j+1].y,o->Pts_Controle_recalcule.table[j+1].z);
    }
    glEnd();


    glBegin(GL_POINT);
    glColor3d(1,0,0);
    for(j=0 ; j< o->Courbe_reparametree.nb; j++){
        if((o->Courbe_reparametree.table[j].x==0 && o->Courbe_reparametree.table[j].y==0 &&o->Courbe_reparametree.table[j].z==0) || (o->Courbe_reparametree.table[j+1].x==0 && o->Courbe_reparametree.table[j+1].y==0 &&o->Courbe_reparametree.table[j+1].z==0)) {}
        else{
            glVertex3f(o->Courbe_reparametree.table[j].x,o->Courbe_reparametree.table[j].y,o->Courbe_reparametree.table[j].z);
        }
    }
    glEnd();

}



CLASSE(reparametrage, struct reparametrage,

    CHAMP(Pts_Controle_recalcule, L_table_point P_table_quadruplet
             Affiche Sauve)

    CHAMP(Pts_Controle, L_table_point P_table_quadruplet
             Extrait Obligatoire  Affiche Sauve)

    CHAMP(Courbe_reparametree, L_table_point P_table_quadruplet
            Affiche Sauve)

    CHAMP(nb_points, LABEL("Nombre de points")
             L_entier Extrait Affiche Edite Sauve DEFAUT("101"))

    CHAMP(debut, LABEL("Debut")
             L_entier Extrait Edite Affiche Sauve DEFAUT("20"))

    CHAMP(fin, LABEL("Fin")
             L_entier Extrait Affiche Edite Sauve DEFAUT("90"))

    CHANGEMENT(changement_reparametrage)
    CHAMP_VIRTUEL(L_affiche_gl(affiche_courbe_reparametree))

    MENU("Courbe Reparametree")
    EVENEMENT("CR")
)


//
//#include <GL/gl.h>
//#include <math.h>
//#include <stdio.h>
//
//#include "o_objet.h"
//#include "u_table.h"
//#include "t_geometrie.h"
//
//struct reparametrage
//{
//  Table_triplet Pts_Controle_recalcule;
//  Table_triplet Pts_Controle;
//  Table_triplet Courbe_reparametree;
//  int nb_points;
//  int debut;
//  int fin;
//};
//
///*/// ################################################################################################################################ \\\*/
//
//Table_triplet calcul_pt_control_debut(struct reparametrage *o)
//{
//    int i,j;
//    double debut = 1.0*o->debut/100;
//
//    for(i=0;i<o->Pts_Controle.nb;i++)
//        o->Pts_Controle_recalcule.table[i] = o->Pts_Controle.table[i];
//
//    for(i=1;i<o->Pts_Controle.nb;i++)
//    {
//        for(j=0;j<o->Pts_Controle.nb-i;j++)
//        {
//            o->Pts_Controle_recalcule.table[j].x = (1 - debut) * o->Pts_Controle_recalcule.table[j].x + debut * o->Pts_Controle_recalcule.table[j+1].x;
//            o->Pts_Controle_recalcule.table[j].y = (1 - debut) * o->Pts_Controle_recalcule.table[j].y + debut * o->Pts_Controle_recalcule.table[j+1].y;
//            o->Pts_Controle_recalcule.table[j].z = (1 - debut) * o->Pts_Controle_recalcule.table[j].z + debut * o->Pts_Controle_recalcule.table[j+1].z;
//        }
//    }
//    return o->Pts_Controle_recalcule;
//}
//
//Table_triplet calcul_pt_control_fin(struct reparametrage *o)
//{
//    int i,j;
//    Table_triplet points_temp;
//    ALLOUER(points_temp.table,o->Pts_Controle_recalcule.nb);
////    points_temp.table = malloc(o->Pts_Controle_recalcule.nb*sizeof(Triplet));
//    double fin = 1.0*o->fin/100;
//
//    for(i=0;i<o->Pts_Controle_recalcule.nb;i++)
//        points_temp.table[i]=o->Pts_Controle_recalcule.table[i];
//
//    for(i=1;i<o->Pts_Controle.nb;i++)
//    {
//        for(j=0;j<o->Pts_Controle.nb-i;j++)
//        {
//            if(j==0)
//            {
//                o->Pts_Controle_recalcule.table[i].x = (1 - fin) * points_temp.table[j].x + fin * points_temp.table[j+1].x;
//                o->Pts_Controle_recalcule.table[i].y = (1 - fin) * points_temp.table[j].y + fin * points_temp.table[j+1].y;
//                o->Pts_Controle_recalcule.table[i].z = (1 - fin) * points_temp.table[j].z + fin * points_temp.table[j+1].z;
//            }
//
//            points_temp.table[j].x = (1 - fin) * points_temp.table[j].x + fin * points_temp.table[j+1].x;
//            points_temp.table[j].y = (1 - fin) * points_temp.table[j].y + fin * points_temp.table[j+1].y;
//            points_temp.table[j].z = (1 - fin) * points_temp.table[j].z + fin * points_temp.table[j+1].z;
//        }
//    }
//    return o->Pts_Controle_recalcule;
//}
//
///*/// ################################################################################################################################ \\\*/
//
//Triplet calcul_point_courbe(struct reparametrage *o,double pas) /// crée la courbe reparametrée
//{
//    int i,j;
//    Table_triplet points_temp;
//    ALLOUER(points_temp.table,o->Courbe_reparametree.nb);
////    points_temp.table = malloc(o->Courbe_reparametree.nb*sizeof(Triplet));
//
//    for(j=0;j < o->Pts_Controle_recalcule.nb;j++)
//        points_temp.table[j] = o->Pts_Controle_recalcule.table[j];
//
//    for(i=1;i < o->Pts_Controle_recalcule.nb;i++)
//    {
//        for(j=0;j<o->Pts_Controle_recalcule.nb-i;j++)
//        {
//            points_temp.table[j].x = (1 - pas) * points_temp.table[j].x + pas * points_temp.table[j+1].x;
//            points_temp.table[j].y = (1 - pas) * points_temp.table[j].y + pas * points_temp.table[j+1].y;
//            points_temp.table[j].z = (1 - pas) * points_temp.table[j].z + pas * points_temp.table[j+1].z;
//        }
//    }
//    return points_temp.table[j-1];
//}
//
//Table_triplet calcul_reparametrage(struct reparametrage *o)
//{
//    double i;
//    double pas =0.0;
//    int indice = 0;
//    pas = 1.0/o->nb_points;
//
//    for(i = 0; i <= 1 ;i+=pas,indice++)
//        o->Courbe_reparametree.table[indice] = calcul_point_courbe(o,i);
//
//    return o->Courbe_reparametree;
//}
//
//
//static void changement_reparametrage(struct reparametrage *o)
//{
//    if ( ! (UN_CHAMP_CHANGE(o)||CREATION(o)) )
//        return;
//
//    if (CHAMP_CHANGE(o, nb_points) ||  CHAMP_CHANGE(o, Pts_Controle) || CHAMP_CHANGE(o, debut) || CHAMP_CHANGE(o, fin) )
//    {
//        if (o->nb_points > 0 || o->Courbe_reparametree.nb >=2 || o->Pts_Controle_recalcule.nb >=0 ||o->debut != 0 || o->fin != 100)
//        {
//            free(o->Courbe_reparametree.table);
//            free(o->Pts_Controle_recalcule.table);
//        }
//
//        o->Pts_Controle_recalcule.table = malloc((o->Pts_Controle.nb)*sizeof(Triplet));
//        o->Pts_Controle_recalcule.nb = o->Pts_Controle.nb;
//
//      o->Courbe_reparametree.table = malloc((o->nb_points)*sizeof(Triplet));
//      o->Courbe_reparametree.nb = o->nb_points;
//
//        o->Pts_Controle_recalcule=calcul_pt_control_debut(o);
//        o->Pts_Controle_recalcule=calcul_pt_control_fin(o);
//
//        o->Courbe_reparametree=calcul_reparametrage(o);
//
//      printf("dans changement Bezier\n");
//    }
//}
//
//
//static void affiche_courbe_reparametree(struct reparametrage *o)
//{
//    int j;
//
//    glBegin(GL_LINE) ;
//    glColor3d(1,0,0);
//    for(j=0; j < o->Pts_Controle_recalcule.nb-1; j++){
//        glVertex3f(o->Pts_Controle_recalcule.table[j].x,o->Pts_Controle_recalcule.table[j].y,o->Pts_Controle_recalcule.table[j].z);
//        glVertex3f(o->Pts_Controle_recalcule.table[j+1].x,o->Pts_Controle_recalcule.table[j+1].y,o->Pts_Controle_recalcule.table[j+1].z);
//    }
//    glEnd();
//
//
//    glBegin(GL_POINT);
//    glColor3d(1,0,0);
//    for(j=0 ; j< o->Courbe_reparametree.nb; j++){
//        if((o->Courbe_reparametree.table[j].x==0 && o->Courbe_reparametree.table[j].y==0 &&o->Courbe_reparametree.table[j].z==0) || (o->Courbe_reparametree.table[j+1].x==0 && o->Courbe_reparametree.table[j+1].y==0 &&o->Courbe_reparametree.table[j+1].z==0)) {}
//        else{
//            glVertex3f(o->Courbe_reparametree.table[j].x,o->Courbe_reparametree.table[j].y,o->Courbe_reparametree.table[j].z);
//        }
//    }
//    glEnd();
//
//}
//
//
//
//CLASSE(reparametrage, struct reparametrage,
//
//    CHAMP(Pts_Controle_recalcule, L_table_point P_table_triplet
//             Affiche Sauve)
//
//    CHAMP(Pts_Controle, L_table_point P_table_triplet
//             Extrait Obligatoire  Affiche Sauve)
//
//    CHAMP(Courbe_reparametree, L_table_point P_table_triplet
//            Affiche Sauve)
//
//    CHAMP(nb_points, LABEL("Nombre de points")
//             L_entier Extrait Affiche Edite Sauve DEFAUT("101"))
//
//    CHAMP(debut, LABEL("Debut")
//             L_entier Extrait Edite Affiche Sauve DEFAUT("20"))
//
//    CHAMP(fin, LABEL("Fin")
//             L_entier Extrait Affiche Edite Sauve DEFAUT("90"))
//
//    CHANGEMENT(changement_reparametrage)
//    CHAMP_VIRTUEL(L_affiche_gl(affiche_courbe_reparametree))
//
//    MENU("Courbe Reparametree")
//    EVENEMENT("CR")
//)
